<template>
  <div>
    <div class="contentTopTitle">
      <div class="fl">
        <div class="title">数字生活树</div>
      </div>
    </div>
    <el-form :inline="true" :model="form" label-width="90px" class="formList">
      <el-form-item label="区域">
        <dx-cascader :area_id.sync="form.areaId" :area_name.sync="area_name"
                     @change="handleSearch" />
      </el-form-item>
      <el-form-item label="账期">
        <el-date-picker v-model="form.month" type="month" placeholder="选择账期" :clearable="false"
                        value-format="yyyyMM" @change="handleSearch"></el-date-picker>
      </el-form-item>
      <el-form-item label="展示指标">
        <el-select v-model="form.attrType" multiple collapse-tags placeholder="请选择"
                   @change="handleSearch">
          <el-option v-for="item in indexAttrOptions" :key="item" :label="item" :value="item">
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button size="small" type="primary" @click="handleSearch">查询</el-button>
        <el-button size="small" type="primary" @click="handleExport"
                   :loading="loading">导出</el-button>
      </el-form-item>
    </el-form>

    <div class="myDiagramDiv—container" v-loading="loading">
      <!-- <div id="myOverviewDiv"></div> -->
      <div id="myDiagramDiv"></div>
      <div class="fullScreen-btn btn" @click="setElementFullScreen">
        <i class="el-icon-full-screen"></i>
      </div>
      <div class="increaseZoom-btn btn" @click="increaseZoom">
        <i class="el-icon-plus"></i>
      </div>
      <div class="decreaseZoom-btn btn" @click="decreaseZoom">
        <i class="el-icon-minus"></i>
      </div>

    </div>
  </div>
</template>

<script>
import { $budgetAPI } from "@/api";
import * as go from "gojs";
export default {
    name: "TreeDiagram",

    data() {
        return {
            form: {
                areaId: "",
                attrType: ["收入层"],
                month: this.moment().subtract(1, "month").format("YYYYMM")
            },
            area_name: "",
            myOverview: null,
            myDiagram: null,
            loading: false,
            indexAttrOptions: [],
            diagramData: []
        };
    },

    mounted() {
        this.initDiagram();
        this.getTreeDiagramList();
        this.getIndexAttr();
    },

    destroyed() {
        if (this.myDiagram) {
            this.myDiagram.clear(); // 清空 Diagram 内容
            this.myDiagram.div = null; // 从页面上移除 Diagram 元素
            // this.myOverview = null;
            this.myDiagram = null;
        }
    },

    methods: {
        //加
        increaseZoom() {
            this.myDiagram.commandHandler.decreaseZoom(1.5);
        },
        //减少
        decreaseZoom() {
            this.myDiagram.commandHandler.decreaseZoom(0.5);
        },
        async getTreeDiagramList() {
            try {
                this.loading = true;
                let data = await this.fetch($budgetAPI.getTreeDiagramList, {
                    ...this.form,
                    treeId: 400,
                    reportId: "P400",
                    attrType: this.form.attrType.toString()
                });
                this.diagramData = data.content;
                this.updateModel(this.diagramData);
            } catch (error) {
                console.log(error);
            } finally {
                this.loading = false;
            }
        },
        async getIndexAttr() {
            let data = await this.fetch($budgetAPI.getIndexAttr, { reportId: "P400" });
            this.indexAttrOptions = data.content;
        },
        handleSearch() {
            this.getTreeDiagramList();
        },
        updateModel: function (data) {
            let formatData = data.map((i, index) => {
                return { key: i.indexId, ...i };
            });
            var modelData = {
                nodeParentKeyProperty: "parentIndexId", // Specify the custom parent node property name
                nodeDataArray: formatData // Set the new data array for the nodes
            };
            this.myDiagram.clear();
            var model = new go.TreeModel(modelData);
            this.myDiagram.model = model;
            this.myDiagram.layoutDiagram();
        },
        setElementFullScreen() {
            const dom = document.querySelector("div.myDiagramDiv—container");
            const fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement;
            if (!fullscreenElement) {
                if (dom.requestFullscreen) {
                    dom.requestFullscreen();
                } else if (dom.webkitRequestFullscreen) {
                    dom.webkitRequestFullscreen();
                }
            } else {
                if (document.exitFullscreen) {
                    document.exitFullscreen();
                } else if (document.webkitExitFullscreen) {
                    document.webkitExitFullscreen();
                }
            }
        },
        initDiagram() {
            var $ = go.GraphObject.make; // 使用$符号作为快捷方式
            var myDiagram = $(
                go.Diagram,
                "myDiagramDiv", // 指定图表的容器元素ID
                {
                    // renderer: "svg",
                    // 设置图表的布局
                    layout: $(go.TreeLayout, {
                        angle: 0, // 指定布局的角度为0，从左向右展开
                        arrangement: go.TreeLayout.ArrangementHorizontal // 设置布局为水平方向
                    }),
                    // 设置画布的大小为100%
                    initialContentAlignment: go.Spot.Center, // 将图表内容居中显示
                    // contentAlignment: go.Spot.Center, // 将图表内容居中对齐
                    // initialDocumentSpot: go.Spot.TopLeft,
                    // initialAutoScale: go.Diagram.Uniform, //初始自动缩放
                    initialScale: 0.8,
                    initialViewportSpot: go.Spot.TopLeft, //初始视口点
                    padding: 10 // 设置画布的内边距
                }
            );

            function textStyle(field) {
                return [
                    {
                        margin: new go.Margin(2, 0, 2, 0),
                        font: "normal 12px sans-serif",
                        stroke: "#424242",
                        alignment: go.Spot.Left,
                        visible: false
                    },
                    new go.Binding("visible", field, (val) => val !== undefined)
                ];
            }
            const levelColors = ["#AC193D", "#2672EC", "#8C0095", "#5133AB", "#008299", "#D24726", "#008A00", "#094AB2"];

            // override TreeLayout.commitNodes to also modify the background brush based on the tree depth level
            myDiagram.layout.commitNodes = function () {
                // method override must be function, not =>
                go.TreeLayout.prototype.commitNodes.call(this); // do the standard behavior
                // then go through all of the vertexes and set their corresponding node's Shape.fill
                // to a brush dependent on the TreeVertex.level value
                myDiagram.layout.network.vertexes.each((v) => {
                    if (v.node) {
                        const level = v.level % levelColors.length;
                        const color = levelColors[level];
                        const TitleShape = v.node.findObject("Title");
                        const Shape = v.node.findObject("SHAPE");
                        const Line = v.node.findObject("Line");
                        // if (TitleShape) TitleShape.stroke = color;
                        // if (Shape) Shape.stroke = color;
                        if (Line) Line.stroke = "#0086ff";
                    }
                });
            };

            // 定义节点模板
            myDiagram.nodeTemplate = $(
                go.Node,
                "Auto",
                { movable: false }, // 添加 movable: false 属性来禁用节点的可拖拽功能
                $(
                    go.Shape,
                    "RoundedRectangle", // 使用圆角矩形作为节点的形状
                    {
                        name: "SHAPE",
                        fill: "#F6F7FC",
                        stroke: "#0086ff", // 设置边框颜色为蓝色
                        strokeWidth: 1, // 设置边框宽度
                        strokeDashArray: [4, 2] // 设置边框为虚线，数组中的两个值分别表示虚线和实线的长度
                    }
                ),
                $(
                    go.Panel,
                    "Horizontal",
                    $(
                        go.Panel,
                        "Vertical",
                        { padding: new go.Margin(5, 10) },

                        $(
                            go.Panel,
                            "Horizontal",
                            { alignment: go.Spot.Left },
                            $(
                                go.TextBlock,
                                {
                                    name: "Title",
                                    margin: new go.Margin(4, 8, 4, 0),
                                    font: "bold 16px sans-serif",
                                    stroke: "#0086ff",
                                    alignment: go.Spot.Left
                                },
                                new go.Binding("text", "indexName")
                            ),
                            $(
                                "PanelExpanderButton",
                                "INFO",
                                {
                                    visible: false
                                }
                                // new go.Binding("visible", "", function (data) {
                                //     return data.dataList.length > 0;
                                // })
                            )
                        ),

                        // $(
                        // 	go.TextBlock,
                        // 	textStyle("indexName"),
                        // 	new go.Binding("text", "indexName", (head) => "收入: " + head)
                        // ),

                        // $(
                        // 	go.Panel,
                        // 	"Vertical",
                        // 	// 使用模板函数来循环遍历节点信息并添加文字信息
                        // 	new go.Binding("itemArray", "dataList"),
                        // 	{
                        // 		alignment: go.Spot.Left,
                        // 		itemTemplate: $(
                        // 			go.Panel,
                        // 			"Vertical",
                        // 			{ alignment: go.Spot.Left },
                        // 			$(
                        // 				go.TextBlock,
                        // 				textStyle("indexName"),
                        // 				new go.Binding("text", "indexName")
                        // 			)
                        // 		),
                        // 	}
                        // ),

                        $(
                            go.Panel,
                            "Vertical",
                            {
                                stretch: go.GraphObject.Fill, // 撑满整个行
                                visible: false
                            },
                            // new go.Binding("visible", "", function (data) {
                            //     return data.dataList.length > 0;
                            // }),
                            $(
                                go.Shape,
                                "LineH",
                                {
                                    name: "Line",
                                    stroke: "rgba(0, 0, 0, .60)",
                                    strokeWidth: 1,
                                    height: 1,
                                    margin: new go.Margin(0, 0, 4, 0),
                                    stretch: go.GraphObject.Horizontal
                                },
                                new go.Binding("visible").ofObject("INFO")
                            )
                        ),

                        $(go.Panel, "Table", { name: "INFO", visible: true }, new go.Binding("itemArray", "dataList"), {
                            alignment: go.Spot.Left,
                            itemTemplate: $(
                                go.Panel,
                                "TableRow",
                                {
                                    visible: false // 默认隐藏行
                                },
                                $(
                                    go.TextBlock,
                                    textStyle("indexId"),
                                    new go.Binding("text", "indexId", (indexId, textBlock) => {
                                        var node = textBlock.part; // 获取节点对象
                                        var data = node.data.dataList; // 获取节点数据对象
                                        let currentObj = data.find((i) => i.indexId == indexId);
                                        let t = `${currentObj.indexName} : ${currentObj.indexValue} `;
                                        return t;
                                    })
                                ),
                                new go.Binding("visible", "", function (data) {
                                    return !data.disabled;
                                })
                            )
                        })
                    ),
                    // 折叠按钮
                    $(
                        go.Panel,
                        "Horizontal",
                        { alignment: go.Spot.Right, visible: true },
                        $("TreeExpanderButton", {
                            width: 14,
                            height: 14,
                            margin: 4,
                            alignment: go.Spot.Right,
                            _buttonFillOver: "lightgray",
                            _buttonStrokeOver: "gray",
                            _buttonFillPressed: "gray",
                            _buttonStrokePressed: "black"
                        })
                    )
                )
            );

            // 定义连线模板
            myDiagram.linkTemplate = $(
                go.Link,
                go.Link.Orthogonal,
                { corner: 2, selectable: false },
                $(go.Shape, { strokeWidth: 1, stroke: "#0086ff" })
            );

            // 定制节点选中时的高亮样式
            myDiagram.nodeTemplate.selectionAdornmentTemplate = $(
                go.Adornment,
                "Auto",
                $(
                    go.Shape,
                    "RoundedRectangle", // 使用圆角矩形作为选中装饰的形状
                    { fill: null, stroke: "dodgerblue", strokeWidth: 2 }
                ), // 设置填充颜色、边框颜色和宽度
                $(go.Placeholder) // 显示节点的内容
            );

            // 在设置节点数据之前，先定义一个节点信息数组
            // let formatData = dataContent.map((i, index) => {
            //     let obj = {
            //         key: i.indexId,
            //         ...i
            //     };

            //     return obj;
            // });

            // // 将数据绑定到图表
            // myDiagram.model = new go.TreeModel({
            //     nodeParentKeyProperty: "parentIndexId", // 指定自定义父节点属性名
            //     nodeDataArray: formatData
            // });

            //添加鸟瞰图
            // var myOverview = $(go.Overview, "myOverviewDiv", {
            //     observed: myDiagram,
            //     contentAlignment: go.Spot.Center
            // });

            this.myDiagram = myDiagram;
            // this.myOverview = myOverview;
        },
        //
        handleExport() {
            var _this = this;
            var pdfFileName = `${this.area_name}_${this.form.month}_${this.form.attrType.join()}`;
            require(["svg2pdf.js/dist/svg2pdf", "jspdf-yworks/dist/jspdf.min"], async function (svg2pdf, jsPDF) {
                console.log("svg2pdf: ", svg2pdf);

                //导出 为图片
                function makeBlob() {
                    _this.myDiagram.makeImageData({
                        scale: 1.5,
                        maxSize: new go.Size(Infinity, Infinity),
                        padding: new go.Margin(20),
                        background: "white",
                        returnType: "blob",
                        callback: myCallback
                    });
                }

                function myCallback(blob) {
                    var url = window.URL.createObjectURL(blob);
                    var filename = pdfFileName + ".png";
                    var a = document.createElement("a");
                    a.style = "display: none";
                    a.href = url;
                    a.download = filename;
                    document.body.appendChild(a);
                    a.click();
                    window.URL.revokeObjectURL(url);
                    document.body.removeChild(a);
                }

                // makeBlob();

                // function getImageSize(url) {
                //     return new Promise((resolve, reject) => {
                //         const img = new Image();
                //         img.onload = function () {
                //             resolve({
                //                 width: img.width,
                //                 height: img.height
                //             });
                //         };
                //         img.onerror = function () {
                //             reject(new Error("Failed to load image"));
                //         };
                //         img.src = url;
                //     });
                // }

                // async function exportImgToPdf(blob) {
                //     var url = window.URL.createObjectURL(blob);
                //     let { width, height } = await getImageSize(url);
                //     const doc = new jsPDF("", "pt", [width, height]);
                //     doc.addImage(url, "JPEG", 0, 0, width, height); // 添加图片到 PDF 文件中
                //     doc.save("example.pdf"); // 保存 PDF 文件到本地
                // }

                // svg 导出 pdf 中文乱码 无解
                const svgElement = _this.myDiagram.makeSvg({
                    scale: 0.5,
                    background: "white"
                });
                const width = svgElement.getAttribute("width").replace(/px/g, "");
                const height = svgElement.getAttribute("height").replace(/px/g, "");
                function pxToPt(px) {
                    return px * 1.0 + 20; // 1 像素 = 0.75 点
                }
                const pdf = new jsPDF("", "pt", [pxToPt(width), pxToPt(height)]);
                pdf.addFont("static/font/fzht.TTF", "MyFont", "normal"); //第二个参数为字体的名字，也是自命名，第三个参数统一为normal
                pdf.setFont("MyFont");

                // await wait(1000);
                svg2pdf(svgElement, pdf, {
                    xOffset: 10,
                    yOffset: 10,
                    scale: 1
                });
                pdf.save(`${pdfFileName}.pdf`);
            });
        }
    }
};
</script>

<style lang="scss" scoped>
.myDiagramDiv—container {
    width: 100%;
    height: calc(100vh - 200px);
    border: solid 1px #f4f4f4;
    background: #fff;
    box-sizing: border-box;
    position: relative;
    #myDiagramDiv {
        width: 100%;
        height: 100%;
    }
    #myOverviewDiv {
        position: absolute;
        width: 200px;
        height: 100px;
        top: 10px;
        left: 10px;
        background-color: #f2f2f2;
        z-index: 300;
        border: solid 1px #7986cb;
    }
    .fullScreen-btn {
        position: absolute;
        top: 10px;
        right: 20px;
    }
    .increaseZoom-btn {
        position: absolute;
        top: 120px;
        right: 20px;
    }
    .decreaseZoom-btn {
        position: absolute;
        top: 180px;
        right: 20px;
    }
    .btn {
        width: 40px;
        height: 40px;
        z-index: 300;
        background: #fff;
        cursor: pointer;
        border-radius: 4px;
        box-shadow: 0px 2px 12px 1px rgba(0, 0, 0, 0.1);
        font-size: 25px;
        display: flex;
        align-items: center;
        justify-content: center;
    }
}
</style>
